﻿using ComputerBeacon.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using ComputerBeacon.Magic.Security;

namespace Json_Test
{
    
    
    /// <summary>
    ///This is a test class for JsonObjectTest and is intended
    ///to contain all JsonObjectTest Unit Tests
    ///</summary>
    [TestClass()]
    public class JsonObjectTest {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext {
            get {
                return testContextInstance;
            }
            set {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize(){
            System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("fr");
        }
        //
        //Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup() {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.GetCultureInfo("fr");
            Assert.AreEqual(culture, System.Threading.Thread.CurrentThread.CurrentCulture);
        }
        //
        #endregion


        RandomNumberGenerator rng = new RandomNumberGenerator(true);
        RandomStringGenerator pg = new RandomStringGenerator(RandomStringGenerator.CharSet.SmallAlphabets);


        /// <summary>
        ///A test for JsonObject Constructor
        ///</summary>
        [TestMethod()]
        public void Ctor() {
            JsonObject target = new JsonObject();
            Assert.AreEqual(0, target.Count);
            Assert.AreEqual("{}", target.ToString());
        }


        [TestMethod]
        public void AnnoymousTypeCtor() {
            JsonObject jo = new JsonObject(new {
                Id = 123,
                Name = "Hello World",
                Photos = new JsonArray(new object[] { 1, 2, 3, 4, 5 })
            });

            Assert.AreEqual(123, jo["Id"]);
            Assert.AreEqual("Hello World", jo["Name"]);

            JsonArray photos = jo["Photos"] as JsonArray;
            for (int i = 0; i < 5; i++) Assert.AreEqual(i+1, photos[i]);
        }



        /// <summary>
        ///A test for Add
        ///</summary>
        [TestMethod()]
        public void JsonObject_AddTest() {
            JsonObject target = new JsonObject();
            for (int i = 0; i < 100; i++) {
                string key = pg.GetString(8, 16);
                uint value = rng.MWC();
                target.Add(key, value);
                Assert.AreEqual(value, target[key]);
            }
        }

        /// <summary>
        ///A test for Clear
        ///</summary>
        [TestMethod()]
        public void JsonObject_ClearTest() {
            JsonObject target = new JsonObject();

            for (int i = 0; i < 100; i++) {
                string key = pg.GetString(8, 16);
                uint value = rng.MWC();
                target.Add(key, value);
            }

            target.Clear();
            Assert.AreEqual(0, target.Count);
        }

        /// <summary>
        ///A test for Contains
        ///</summary>
        [TestMethod()]
        public void JsonObject_ContainsTest() {
            JsonObject target = new JsonObject();
            KeyValuePair<string, object> item = new KeyValuePair<string, object>(pg.GetString(8, 16), pg.GetString(8, 16));

            Assert.AreEqual(false, target.Contains(item));

            target.Add(item.Key, item.Value);
            Assert.AreEqual(true, target.Contains(item));

            for (int i = 0; i < 100; i++) {
                string key = pg.GetString(8, 16);
                string value = pg.GetString(8, 16);
                target.Add(key, value);
                Assert.AreEqual(true, target.Contains(item));
            }

            target.Remove(item.Key);
            Assert.AreEqual(false, target.Contains(item));
        }

        /// <summary>
        ///A test for ContainsKey
        ///</summary>
        [TestMethod()]
        public void JsonObject_ContainsKeyTest() {
            JsonObject target = new JsonObject();
            KeyValuePair<string, object> item = new KeyValuePair<string, object>(pg.GetString(8, 16), pg.GetString(8, 16));

            Assert.AreEqual(false, target.ContainsKey(item.Key));

            target.Add(item.Key, item.Value);
            Assert.AreEqual(true, target.ContainsKey(item.Key));

            for (int i = 0; i < 100; i++) {
                string key = pg.GetString(8, 16);
                string value = pg.GetString(8, 16);
                target.Add(key, value);
                Assert.AreEqual(true, target.ContainsKey(item.Key));
            }

            target.Remove(item.Key);
            Assert.AreEqual(false, target.ContainsKey(item.Key));
        }

        /// <summary>
        ///A test for Keys
        ///</summary>
        [TestMethod()]
        public void JsonObject_KeysTest() {
            JsonObject target = new JsonObject();

            const int trials = 100;
            string[] keys = new string[trials];

            for (int i = 0; i < trials; i++) {
                string key = pg.GetString(8, 16);
                uint value = rng.MWC();
                keys[i] = key;
                target.Add(key, value);
            }

            var orderedKeysExpected = keys.OrderBy(s => s).ToArray();
            var orderedKeysActual = target.Keys.OrderBy(s => s).ToArray();

            for (int i = 0; i < trials; i++) Assert.AreEqual(orderedKeysExpected[i], orderedKeysActual[i]);
        }

        /// <summary>
        ///A test for Values
        ///</summary>
        [TestMethod()]
        public void JsonObject_ValuesTest() {
            JsonObject target = new JsonObject();

            const int trials = 100;
            uint[] values = new uint[trials];

            for (int i = 0; i < trials; i++) {
                string key = pg.GetString(8, 16);
                uint value = rng.MWC();
                values[i] = value;
                target.Add(key, value);
            }

            var orderedValuesExpected = values.OrderBy(s => s).ToArray();
            var orderedValuesActual = target.Values.OrderBy(s => s).ToArray();

            for (int i = 0; i < trials; i++) Assert.AreEqual(orderedValuesExpected[i], orderedValuesActual[i]);
        }

        [TestMethod]
        public void ErrorJO() {
            try {
                JsonObject jo = new JsonObject("[0,1,2,3,4,5]");
                Assert.Fail();
            }
            catch (FormatException) { }
        }

        [TestMethod]
        public void ErrorJA() {
            try {
                JsonArray ja = new JsonArray("{}");
                Assert.Fail();
            }
            catch (FormatException) { }
        }

        [TestMethod]
        public void JsonObject_IndexTest() {
            JsonObject jo = new JsonObject();
            string key = pg.GetString(3, 10);
            uint value = rng.KISS();

            Assert.IsNull(jo[key]);
            jo[key] = value;
            Assert.AreEqual(value, jo[key]);
        }
    }
}
